package org.csu.tank.client;

import com.almasb.fxgl.app.CursorInfo;
import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import com.almasb.fxgl.app.scene.*;
import com.almasb.fxgl.core.math.FXGLMath;
import com.almasb.fxgl.core.util.LazyValue;
import com.almasb.fxgl.dsl.components.HealthIntComponent;
import com.almasb.fxgl.entity.Entity;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.PauseTransition;
import javafx.animation.Timeline;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.util.Duration;
import org.csu.tank.GameConfig;
import org.csu.tank.GameEntityFactory;
import org.csu.tank.GameType;
import org.csu.tank.collision.*;
import org.csu.tank.components.Dir;
import org.csu.tank.components.PlayerComponent;
import org.csu.tank.protocol.MissileNewMsg;
import org.csu.tank.protocol.TankMoveMsg;
import org.csu.tank.ui.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import static com.almasb.fxgl.dsl.FXGL.*;

public class TankClient extends GameApplication {

      private NetClient nc = new NetClient(this);

      private Entity player;

      private PlayerComponent playerComponent;

      //当前客户端击杀人数
      private int enemyKills=0;


      //存储所有坦克组件
      private List<PlayerComponent> playerComponentList = new ArrayList<>();

      private Random random = new Random();

      public LazyValue<FailedScene> failedSceneLazyValue = new LazyValue<>(FailedScene::new);


      //碰撞
      @Override
      protected void initPhysics() {
            getPhysicsWorld().addCollisionHandler(new BulletEnemyHandler());  // 无用的碰撞
            BulletPlayerHandler bulletPlayerHandler = new BulletPlayerHandler(this);
            getPhysicsWorld().addCollisionHandler(bulletPlayerHandler);
            getPhysicsWorld().addCollisionHandler(bulletPlayerHandler.copyFor(GameType.BULLET_ENEMY,GameType.PLAYER));  // 无用的碰撞
            BulletPlayerEnemyHandler bulletPlayerEnemyHandler = new BulletPlayerEnemyHandler(this);
            getPhysicsWorld().addCollisionHandler(bulletPlayerEnemyHandler);
            getPhysicsWorld().addCollisionHandler(bulletPlayerEnemyHandler.copyFor(GameType.BULLET_ENEMY,GameType.PLAYER));   // 无用的碰撞
            BulletBrickHandler bulletBrickHandler = new BulletBrickHandler();
            getPhysicsWorld().addCollisionHandler(bulletBrickHandler);
            getPhysicsWorld().addCollisionHandler(bulletBrickHandler.copyFor(GameType.BULLET, GameType.STONE));         // 无用的碰撞
            getPhysicsWorld().addCollisionHandler(bulletBrickHandler.copyFor(GameType.BULLET, GameType.GREENS));        // 无用的碰撞
//            getPhysicsWorld().addCollisionHandler(new BulletFlagHandler());
            getPhysicsWorld().addCollisionHandler(new BulletBorderHandler());
            getPhysicsWorld().addCollisionHandler(new BulletBulletHandler());                   // 无用的碰撞
            getPhysicsWorld().addCollisionHandler(new PlayerItemHandler());                     // 无用的碰撞
      }


      @Override
      protected void onPreInit() {
            getSettings().setGlobalSoundVolume(0.5);
            getSettings().setGlobalMusicVolume(0.5);
      }

      @Override
      protected void initSettings(GameSettings settings) {
            settings.setWidth(28 * 24 + 6 * 24);
            settings.setHeight(28 * 24);
            settings.setTitle("Tank War Online");
            settings.setAppIcon("ui/icon.png");
            settings.setVersion("Version 1.0");
            settings.setMainMenuEnabled(true);
            settings.setGameMenuEnabled(true);
            settings.getCSSList().add("tankApp.css");
            settings.setDefaultCursor(new CursorInfo("ui/cursor.png", 0, 0));
            //FPS,CPU,RAM等信息的显示
            //settings.setProfilingEnabled(true);
            //开发模式.这样可以输出较多的日志异常追踪
            //settings.setApplicationMode(ApplicationMode.DEVELOPER);
            settings.setSceneFactory(new SceneFactory() {
                  @Override
                  public StartupScene newStartup(int width, int height) {
                        //自定义启动场景
                        return new GameStartupScene(width, height);
                  }

                  @Override
                  public FXGLMenu newMainMenu() {
                        //主菜单场景
                        return new GameMainMenu();
                  }

                  @Override
                  public LoadingScene newLoadingScene() {
                        //游戏前的加载场景
                        return new GameLoadingScene();
                  }
            });
      }

      @Override
      protected void initGameVars(Map<String, Object> vars) {
//            if (getFileSystemService().exists(GameConfig.CUSTOM_LEVEL_PATH)) {
//                  vars.put("level", 0);
//            } else {
//                  vars.put("level", 1);
//            }
            // PVP关卡的值设为-1
            vars.put("level",-1);
            vars.put("playerBulletLevel", 1);
            vars.put("freezingEnemy", false);
            vars.put("destroyedEnemy", 0);
            vars.put("spawnedEnemy", 0);
            vars.put("gameOver", false);
            // 当前关卡的敌人
            vars.put("nowEnemyNum",0);
      }

      @Override
      protected void initInput() {
            onKey(KeyCode.W, this::moveUpAction);
            onKey(KeyCode.UP, this::moveUpAction);

            onKey(KeyCode.S, this::moveDownAction);
            onKey(KeyCode.DOWN, this::moveDownAction);

            onKey(KeyCode.A, this::moveLeftAction);
            onKey(KeyCode.LEFT, this::moveLeftAction);

            onKey(KeyCode.D, this::moveRightAction);
            onKey(KeyCode.RIGHT, this::moveRightAction);

            onKey(KeyCode.SPACE, this::shootAction);
            onKey(KeyCode.F, this::shootAction);
      }


      private boolean tankIsReady() {
            return player != null && playerComponent != null && !getb("gameOver") && player.isActive();
      }


      private void shootAction() {
            if (tankIsReady()) {
                  if (playerComponent.shoot()) {
                        MissileNewMsg msg = new MissileNewMsg(playerComponent.getId());
                        nc.send(msg);
//                        System.out.println(playerComponent.getId() + "的子弹");
                  }
            }
      }

      private void moveRightAction() {
            if (tankIsReady()) {
                  playerComponent.right();
            }
            TankMoveMsg msg
                    = new TankMoveMsg(playerComponent.getId(), player.getX(), player.getY(), Dir.RIGHT, Dir.UP);
//            System.out.println(player.getX() + "   " + player.getY());
            nc.send(msg);
      }

      private void moveLeftAction() {
            if (tankIsReady()) {
                  playerComponent.left();
            }
            TankMoveMsg msg
                    = new TankMoveMsg(playerComponent.getId(), player.getX(), player.getY(), Dir.LEFT, Dir.UP);
            nc.send(msg);
      }

      private void moveDownAction() {
            if (tankIsReady()) {
                  playerComponent.down();
            }
            TankMoveMsg msg
                    = new TankMoveMsg(playerComponent.getId(), player.getX(), player.getY(), Dir.DOWN, Dir.UP);
            nc.send(msg);
      }

      private void moveUpAction() {
            if (tankIsReady()) {
                  playerComponent.up();
            }
            TankMoveMsg msg
                    = new TankMoveMsg(playerComponent.getId(), player.getX(), player.getY(), Dir.UP, Dir.UP);
            nc.send(msg);
      }

      @Override
      protected void initGame() {
            getGameScene().setBackgroundColor(Color.BLACK);
            getGameWorld().addEntityFactory(new GameEntityFactory());

            //TODO 判断
            buildAndStartLevel();
            getip("destroyedEnemy").addListener((ob, ov, nv) -> {
                  if (nv.intValue() == GameConfig.ENEMY_AMOUNT) {
                        set("gameOver", true);
                        play("Win.wav");
                        runOnce(
                                () -> getSceneService().pushSubScene(new SuccessScene()),
                                Duration.seconds(1.5));
                  }
            });
      }

      public void buildAndStartLevel() {
            //1. 清理上一个关卡的残留(这里主要是清理声音残留)
            //清理关卡的残留(这里主要是清理声音残留)
            getGameWorld().getEntitiesByType(
                    GameType.BULLET, GameType.ENEMY, GameType.PLAYER
            ).forEach(Entity::removeFromWorld);

            //2. 开场动画
            Rectangle rect1 = new Rectangle(getAppWidth(), getAppHeight() / 2.0, Color.web("#333333"));
            Rectangle rect2 = new Rectangle(getAppWidth(), getAppHeight() / 2.0, Color.web("#333333"));
            rect2.setLayoutY(getAppHeight() / 2.0);
//            Text text = new Text("STAGE " + geti("level"));
            Text text = new Text(" P V P ");
            text.setFill(Color.WHITE);
            text.setFont(new Font(35));
            text.setLayoutX(getAppWidth() / 2.0 - 50);
            text.setLayoutY(getAppHeight() / 2.0);
            Pane p1 = new Pane(rect1, rect2, text);

            addUINode(p1);

            Timeline tl = new Timeline(
                    new KeyFrame(Duration.seconds(1.2),
                            new KeyValue(rect1.translateYProperty(), -getAppHeight() / 2.0),
                            new KeyValue(rect2.translateYProperty(), getAppHeight() / 2.0)
                    ));
            tl.setOnFinished(e -> removeUINode(p1));

            PauseTransition pt = new PauseTransition(Duration.seconds(1.5));
            pt.setOnFinished(e -> {
                  text.setVisible(false);
                  tl.play();
                  //3. 开始新关卡
                  startLevel();
            });
            pt.play();
      }

      /**
       *
       **/
      private void startLevel() {

            set("gameOver", false);
            //清除上一关残留的道具影响
            set("freezingEnemy", false);
            //恢复消灭敌军数量
            set("destroyedEnemy", 0);
            //恢复生成敌军的数量
            set("spawnedEnemy", 0);

//            //如果关卡是 0 ,那么从用户自定义地图开始游戏
//            if (geti("level") == 0) {
//                  Level level;
//                  try {
//                        level = new TMXLevelLoader()
//                                .load(new File(GameConfig.CUSTOM_LEVEL_PATH).toURI().toURL(), getGameWorld());
//                        getGameWorld().setLevel(level);
//                  } catch (MalformedURLException e) {
//                        throw new RuntimeException(e);
//                  }
//            } else {
//                  setLevelFromMap("level" + geti("level") + ".tmx");
//            }
            // 开启PVP关卡
            setLevelFromMap("PVPlevel.tmx");
            play("start.wav");
            //本机坦克
            player = null;
            //TODO id随机给或者账号，出生地点改成随机，阵营分奇偶
//            player = spawn("player", 605,24);
            // 随机出生点
            player = spawn("player", FXGLMath.random(GameConfig.PVP_BIRTH_POSITION).get());
//            //每局开始玩家坦克都有无敌保护时间
//            player.getComponent(EffectComponent.class).startEffect(new HelmetEffect());
            playerComponent = player.getComponent(PlayerComponent.class);
//            int id = random(2, 10000);
//            playerComponent.setId(id);
//            System.out.println("当前坦克id：" + id);
            //坦克id连接后放入
            playerComponent.setGood(true);
            playerComponentList.add(playerComponent);
            nc.connect("192.168.114.225");
//            nc.connect("127.0.0.1");
//            creatNewPlayer(1,9*12+3,25*6,Dir.DOWN,true);

            //显示信息的UI
            getGameScene().addGameView(new GameView(new PVPInfoPane(), 100));
      }

      public void creatNewPlayer(int id,int hp, double x, double y, Dir dir, boolean good) {
            Entity player = spawn("playerEnemy", x, y);
//            //每局开始玩家坦克都有无敌保护时间
//            player.getComponent(EffectComponent.class).startEffect(new HelmetEffect());
            PlayerComponent newPlayerComponent = player.getComponent(PlayerComponent.class);
            newPlayerComponent.setId(id);
            newPlayerComponent.getEntity().getComponent(HealthIntComponent.class).setValue(hp);
            newPlayerComponent.setName("坦克");
            newPlayerComponent.setMoveDir(dir);
            newPlayerComponent.setGood(good);
            playerComponentList.add(newPlayerComponent);
            inc("nowEnemyNum",1);
            System.out.println(geti("nowEnemyNum"));
      }


      public static void main(String[] args) {
            launch(args);
      }


      public Entity getPlayer() {
            return player;
      }

      public PlayerComponent getPlayerComponent() {
            return playerComponent;
      }

      public List<PlayerComponent> getPlayerComponentList() {
            return playerComponentList;
      }

      public void setPlayerComponentList(List<PlayerComponent> playerComponentList) {
            this.playerComponentList = playerComponentList;
      }

      public NetClient getNc() {
            return nc;
      }

      public void setNc(NetClient nc) {
            this.nc = nc;
      }

      public int getEnemyKills() {
            return enemyKills;
      }

      public void setEnemyKills(int enemyKills) {
            this.enemyKills = enemyKills;
      }

      public void addKills(){
            enemyKills++;
            System.out.println("击杀加一");
      }
}
